package com.army.study.component;

import com.army.study.bean.MyPoint;
import ohos.agp.components.Component;
import ohos.agp.render.Canvas;
import ohos.agp.render.Paint;
import ohos.agp.utils.Color;
import ohos.agp.utils.Point;
import ohos.app.Context;
import ohos.eventhandler.EventHandler;
import ohos.eventhandler.EventRunner;
import ohos.eventhandler.InnerEvent;
import ohos.multimodalinput.event.TouchEvent;

import java.util.ArrayList;
import java.util.List;
import java.util.Timer;
import java.util.TimerTask;

/**
 * 存放所有绘制点的基本信息和绘图
 */
public class DrawPoint extends Component implements Component.DrawTask {
    private static final String TAG = DrawPoint.class.getName();

    // 画笔
    private Paint paint;
    // 描边宽度。
    private int strokeWidth = 15;
    // 画笔颜色
    private Color paintColor;
    // 透明度
    private float paintAlpha = 1.0f;
//    // 画笔拥有颜色数组
//    private final Color[] paintColors = new Color[] {Color.RED, Color.BLUE, Color.BLACK};
    // 定时器
    private Timer timer = null;
    // 定时器任务
    private TimerTask timerTask = null;
    // 时期, 一段时间
    private static final int TIME = 200;
    // 事件信息标识
    private static final int EVENT_MSG_STORE = 0x1000002;
    // 绘画回调
    private OnDrawCallBack callBack;
    // 初始化绘画点集合
    private List<MyPoint> points = new ArrayList<>(0);
    // 记录撤消画点集合, 用于重做时使用
    private List<MyPoint> redoPoints = new ArrayList<>(0);
//    // 记录上一步操作点集合数
//    private int beforePointTotal = 0;

    /**
     * 带参构造方法
     * @param context
     * @param color
     */
    public DrawPoint(Context context, Color color) {
        super(context);
        // 初始化颜色
        init(color);
    }

    /**
     * 初始化画笔
     * @param color
     */
    private void init(Color color) {
        paintColor = color;
        paint = new Paint();
        // 设置 Paint 对象的抗锯齿。
        paint.setAntiAlias(true);
        // 设置 Paint 对象的样式属性(指示笔画类型，具有此样式的几何体将被描边。)
        paint.setStyle(Paint.Style.STROKE_STYLE);
        // 设置 Paint 对象的描边宽度。
        paint.setStrokeWidth(strokeWidth);
        paint.setAlpha(paintAlpha);
        // 添加绘图任务
        addDrawTask(this);

        // 设置触摸事件监听
        setTouchEventListener((component, touchEvent) -> {
            // 计划任务启动
            scheduledTask();

            // 画笔的X和Y坐标值
            int crtX = (int)touchEvent.getPointerPosition(touchEvent.getIndex()).getX();
            int crtY = (int)touchEvent.getPointerPosition(touchEvent.getIndex()).getY();

            // 根据X和Y坐标值,得到一个点
            MyPoint point = new MyPoint(crtX, crtY);
            // 设置点的颜色
            point.setPaintColor(paintColor);
            // 设置点的粗细
            point.setPaintSize(strokeWidth);
            // 设置透明度
            point.setPaintAlpha(paintAlpha);

            switch (touchEvent.getAction()) {
                // 如果是画笔在移动,把所有点都保存到points集合
                case TouchEvent.POINT_MOVE:
                    points.add(point);
                    break;
                // 如果画笔提起来, 说明结束了,并把points回调
                case TouchEvent.PRIMARY_POINT_UP:
//                    if(cancelDraw()) {
//                        if (points.size()>0) points.remove(points.size()-1);
//                        if (beforePointTotal>0) beforePointTotal--;
//                        break;
//                    }

                    points.add(point);
                    // 标识为最后一笔
                    point.setLastPoint(true);
//                    // 保存当前点集合数
//                    beforePointTotal = points.size();
                    // 回调所画的所有点
                    callBack.callBack(points);
                    // 取消计划的任务
                    onTimerFinish();
                    break;
                default:
                    break;
            }
            // 需要更新UI显示时，可调用invalidate()方法
            invalidate();
            return true;
        });
    }

//    private boolean cancelDraw() {
//        LogUtil.info(TAG, "tmpBeforePoints::" + beforePointTotal);
//        int afterPointTotal = points.size();
//        LogUtil.info(TAG, "tmpAfterPoints::" + afterPointTotal);
//        if (afterPointTotal-beforePointTotal < 8) {
//            return true;
//        }
//
//        return false;
//    }

    /**
     * 设置画笔颜色
     * @param color
     */
    public void setPaintColor(Color color) {
        paintColor = color;
    }

    /**
     * 设置画笔粗细
     * @param strokeWidth
     */
    public void setStrokeWidth(int strokeWidth) {
        this.strokeWidth = strokeWidth;
    }

    /**
     * 设置透明度
     * @param paintAlpha
     */
    public void setPaintAlpha(float paintAlpha) {
        this.paintAlpha = paintAlpha;
    }

    /**
     * 取消计划的任务
     */
    public void onTimerFinish() {
        timer.cancel();
        timer = null;
        timerTask = null;
    }

    /**
     * 计划任务启动
     */
    public void scheduledTask() {
        // 如果定时器和定时器任务都为空
        if (timer == null && timerTask == null) {
            // 初始化一个定时器
            timer = new Timer();
            // 初始化一个定时器任务
            timerTask = new TimerTask() {
                @Override
                public void run() {
                    // 发送事件任务
                    handler.sendEvent(EVENT_MSG_STORE);
                }
            };
            // 立刻执行, 并在TIME相隔一段时间执行
            timer.schedule(timerTask, 0, TIME);

        }
    }

    // 初始一个事件任务
    private final EventHandler handler = new EventHandler(EventRunner.current()) {
        @Override
        protected void processEvent(InnerEvent event) {
            if (EVENT_MSG_STORE == event.eventId) {
                // 回调所画的点集合
                callBack.callBack(points);
            }
        }
    };

    /**
     * 回调绘画接口
     */
    public interface OnDrawCallBack {
        // 触摸监听
        void callBack(List<MyPoint> points);
    }

    /**
     * 获取全部点集合
     * @return
     */
    public List<MyPoint> getPoints() {
        return points;
    }

    /**
     * 获取撤消点集合, 用于恢复
     * @return
     */
    public List<MyPoint> getRedoPoints() {
        return this.redoPoints;
    }

    /**
     * 设置参数所画的点集合,更新到UI
     * @param points
     */
    public void setDrawParams(List<MyPoint> points) {
        this.points = points;
        // 需要更新UI显示时，可调用invalidate()方法
        invalidate();
    }

    /**
     * 把撤消点集合保存
     * @param redoPoints
     */
    public void setDrawRedoPoints(List<MyPoint> redoPoints) {
        this.redoPoints = redoPoints;
    }

    /**
     * 设置回调方法
     * @param onCallBack
     */
    public void setOnDrawBack(OnDrawCallBack onCallBack) {
        this.callBack = onCallBack;
    }

//    /**
//     * 根据颜色下标，随机获取颜色
//     * @param colorIndex
//     * @return
//     */
//    private Color getRandomColor(int colorIndex) {
//        // 如果参数大于画笔颜色数组长度，使用第一种颜色
//        return colorIndex > paintColors.length - 1 ? paintColors[0] : paintColors[colorIndex];
//    }

    @Override
    public void onDraw(Component component, Canvas canvas) {
        // 把所有点集合,画到画布下
        draw(points, canvas);
    }

    /**
     * 把所有点集合,画到画布下
     * @param myPoints
     * @param canvas
     */
    private void draw(List<MyPoint> myPoints, Canvas canvas) {
        if (myPoints == null || myPoints.size() <= 1) {
            return;
        }
        // 第一笔为最近一笔
        Point first = null;
        // 最后一笔
        Point last = null;

        for (MyPoint myPoint : myPoints) {
            // 设置画笔颜色
            paint.setColor(myPoint.getPaintColor());
            // 设置画笔粗细
            paint.setStrokeWidth(myPoint.getPaintSize());
            // 设置透明度
            paint.setAlpha(myPoint.getPaintAlpha());
            // 获取X坐标值
            float finalX = myPoint.getPositionX();
            // 获取Y坐标值
            float finalY = myPoint.getPositionY();
            // 初始化点
            Point finalPoint = new Point(finalX, finalY);
            // 如果是最后一点, 跳过
            if (myPoint.isLastPoint()) {
                first = null;
                last = null;
                continue;
            }
            // 记录第一笔
            if (first == null) {
                first = finalPoint;
            } else {
                // 如果不是最后一笔
                if (last != null) {
                    // 第一笔为上一笔
                    first = last;
                }
                // 更新最近一笔为最后一笔
                last = finalPoint;
                // 把点画到画布上
                canvas.drawLine(first, last, paint);
            }
        }
    }

}
